package cc.admin.modules.wea.job;

import cc.admin.common.util.MD5Util;
import cc.admin.common.util.RedisUtil;
import cc.admin.modules.quartz.job.AbstractJob;
import cc.admin.modules.wea.entity.*;
import cc.admin.modules.wea.service.*;
import cc.admin.modules.wea.utils.WeatherUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import springfox.documentation.spring.web.json.Json;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;

/**
 * @author feng
 * @version V1.0
 * @Package cc.admin.modules.wea.job
 * @date 2024/8/29 16:35
 */
@Slf4j
public class WeaWarningJob extends AbstractJob {

    @Autowired
    IWeaStormWarningService weaStormWarningService;

    @Autowired
    IWeaWaveWarningService weaWaveWarningService;

    @Autowired
    IWeaWeatherWarningService weaWeatherWarningService;

    @Autowired
    IWeaSeaFogService weaSeaFogService;
    @Autowired
    IWeaSeaConditionsService weaSeaConditionsService;
    @Autowired
    IWeaSeaIceService weaSeaIceService;
    @Autowired
    IWeaPlatformService weaPlatformService;
    @Autowired
    IWeaTsunamiService weaTsunamiService;
    @Autowired
    IWeaTyphoonTrackService weaTyphoonTrackParentService;
    @Autowired
    IWeaTyphoonForecastService weaTyphoonForecastParentService;
    @Autowired
    IWeaTyphoonForecastDetailService weaTyphoonForecastService;
    @Autowired
    IWeaTyphoonTrackDetailService weaTyphoonTrackService;
    @Autowired
    IWeaSevenForecastService weaSevenForecastService;
    @Autowired
    IWeaWarningRecordService weaWarningRecordService;


    @Autowired
    RedisUtil redisUtil;


    @Override
    public void doExecute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        List<WeaPlatform> platformList = weaPlatformService.getPlatformAll();

        processTsunami();
        processTyphoon();
        processSeaIce();
        processWaveWarning();
        processStormWarning();

        for (WeaPlatform platform : platformList) {
            processSevenForecast(platform);
            processSeaFog(platform);
            processSeaConditions(platform);
            weaWarningRecordService.createWeaWarningRecordList(platform.getId());
        }

        log.info("WeaWarningJob执行完毕");
    }

    /**
     * 七天预报
     * @param platform
     */

    private void processSevenForecast(WeaPlatform platform) {
        String data = WeatherUtil.getWeather(WeatherConstant.SEVEN_DAY_FORECAST, platform.getLon() + "," + platform.getLat());
      List<Map<String, Object>> list = JSON.parseObject(data,new TypeReference<List<Map<String, Object>>>() {});
      // 创建一个包含列表的 Map
      Map<String, Object> resultMap = new HashMap<>();
      resultMap.put("data", list);
      // 将包含列表的 Map 转换为 JSON 字符串
      String jsonMapString = JSON.toJSONString(resultMap);
        handleWarning(jsonMapString, "SevenForecastMD5" + platform.getId(), "SevenForecast" + platform.getId(),platform.getId(),
                WeaSevenForecast::new, weaSevenForecastService,WeatherConstant.SEVEN_DAY_FORECAST);
    }


    /**
     * 台风预警
     */
    private void processTyphoon() {
        //获取当前年份
        SimpleDateFormat year= new SimpleDateFormat("yyyy");
        Date date = new Date(System.currentTimeMillis());
        String data = WeatherUtil.getWeather(WeatherConstant.TROPICAL_CYCLONE_YEAR,year.format(date));
        redisUtil.set("typhoonList", data);
        JSONArray typhoonList = JSON.parseArray(data);
        for(int i = 0; i < typhoonList.size(); i++){
            JSONObject typhoonEventID  = typhoonList.getJSONObject(i);
            //判断列表中的台风是否活跃
            if("active".equals(typhoonEventID.getString("status"))){
                //判断是否在6小时内
                Date nowTime = new Date();
                Date oldTime = DateUtil.parse(typhoonEventID.getString("updatetime"));
                long betweenMinute = DateUtil.between(oldTime, nowTime, DateUnit.HOUR);

                if(betweenMinute<24){

                    WeaTyphoonForecast forecastParent = new WeaTyphoonForecast(typhoonEventID.getString("code"));

                    WeaTyphoonTrack trackParent = new WeaTyphoonTrack(typhoonEventID.getString("code"));


                    int trackIndex = 0,forecastIndex = 0;

                    JSONArray typhoonTrackList = JSON.parseArray(WeatherUtil.getWeather(WeatherConstant.TROPICAL_CYCLONE_TRACK,
                            typhoonEventID.getString("code")));
                    JSONArray typhoonForecastList = JSON.parseArray(WeatherUtil.getWeather(WeatherConstant.TROPICAL_CYCLONE_FORECAST,
                            typhoonEventID.getString("code")));

                    //处理相关数据
                    for(int j = 0; j < typhoonTrackList.size(); j++) {
                        String track = typhoonTrackList.getString(j);
                        if (track != null) {
                           trackIndex += handleWarning(track, "TyphoonTrack" + j + "MD5"+typhoonEventID.getString("code"),
                                   "TyphoonTrack" + j + typhoonEventID.getString("code"),trackParent.getId(),
                                    WeaTyphoonTrackDetail::new, weaTyphoonTrackService, WeatherConstant.TROPICAL_CYCLONE_TRACK);
                        }
                    }

                    for(int k = 0; k < typhoonForecastList.size(); k++){
                        String forecast = typhoonForecastList.getString(k);
                        if(forecast != null){
                            forecastIndex += handleWarning(forecast, "TyphoonForecast"+k+"MD5" + typhoonEventID.getString("code"),
                                    "TyphoonForecast"+ k + typhoonEventID.getString("code"),forecastParent.getId(),
                                    WeaTyphoonForecastDetail::new, weaTyphoonForecastService,WeatherConstant.TROPICAL_CYCLONE_FORECAST);
                        }
                    }

                    if(trackIndex > 0){
                        weaTyphoonTrackParentService.saveOrUpdate(trackParent);
                    }

                    if(forecastIndex > 0){
                        weaTyphoonForecastParentService.saveOrUpdate(forecastParent);
                    }


                }else {
                    log.info("台风预警数据过期，不处理:{}",typhoonEventID.getString("name"));
                }
            }else {
                log.info("台风不活跃:{}",typhoonEventID.getString("name"));
            }

        }
    }

    /**
     * 海啸预警
     *
     */
    private void processTsunami() {
        //获取海啸预警列表
        String tsunamiList = WeatherUtil.getWeather(WeatherConstant.TSUNAMI_WARNING_LIST);
        //比对海啸列表是否变化
        String storedMd5 = (String) redisUtil.get("tsunamiList");
        JSONArray tsunamiEventIDList = JSON.parseArray(tsunamiList);
        //变化则进行下一步
        if (storedMd5 == null || "".equals(storedMd5) || !tsunamiList.equals(storedMd5)) {
            //列表更新
            redisUtil.set("tsunamiList",tsunamiList);
            for(int i = 0; i < tsunamiEventIDList.size(); i++){
                JSONObject tsunamiEventID  = tsunamiEventIDList.getJSONObject(i);
                String tsunami = WeatherUtil.getWeather(WeatherConstant.TSUNAMI_WARNING_DETAIL, tsunamiEventID.getString("eventID"));
                if(tsunami != null){
                    handleWarning(tsunami, "Tsunami"+i+"MD5" , "Tsunami"+i ,"1",
                            WeaTsunami::new, weaTsunamiService,WeatherConstant.TSUNAMI_WARNING_DETAIL);
                }
            }
        }else {
            //列表未更新
            JSONObject tsunamiEventID  = tsunamiEventIDList.getJSONObject(0);
            String tsunami = WeatherUtil.getWeather(WeatherConstant.TSUNAMI_WARNING_DETAIL, tsunamiEventID.getString("eventID"));
            if(tsunami != null){
                handleWarning(tsunami, "Tsunami"+0+"MD5", "Tsunami"+0,"1",
                        WeaTsunami::new, weaTsunamiService,WeatherConstant.TSUNAMI_WARNING_DETAIL);
            }
        }

    }

    /**
     * 海冰
     *
     */
    private void processSeaIce() {
        String seaFog = WeatherUtil.getWeather(WeatherConstant.SEA_ICE_WARNING);
        if(seaFog!= null){
            handleWarning(seaFog, "SeaIceMD5", "SeaIce","1",
                    WeaSeaIce::new, weaSeaIceService,WeatherConstant.SEA_ICE_WARNING);
        }
    }

    /**
     * 实况天气详细情况
     * @param platform
     */
    private void processSeaConditions(WeaPlatform platform) {
        String seaFog = WeatherUtil.getWeather(WeatherConstant.SEA_CONDITIONS, platform.getLon() + "," + platform.getLat());
        if(seaFog!= null){
            handleWarning(seaFog, "SeaConditionsMD5" + platform.getId(), "SeaConditions" + platform.getId(),platform.getId(),
                    WeaSeaConditions::new, weaSeaConditionsService,WeatherConstant.SEA_CONDITIONS);
        }
    }

    /**
     * 海雾
     * @param platform
     */
    private void processSeaFog(WeaPlatform platform) {

        String seaFog = WeatherUtil.getWeather(WeatherConstant.SEA_FOG, platform.getLon() + "," + platform.getLat());
        if(seaFog!= null){
            handleWarning(seaFog, "SeaFogMD5" + platform.getId(), "SeaFog" + platform.getId(),platform.getId(),
                    WeaSeaFog::new, weaSeaFogService,WeatherConstant.SEA_FOG);
        }
    }

    /**
     * 风暴潮
     *
     */
    private void processStormWarning() {
        String stormWarning0 = WeatherUtil.getWeather(WeatherConstant.STORM_WARNING, "0");
        handleWarning(stormWarning0, "Storm0MD5" , "Storm0","1",
                WeaStormWarning::new, weaStormWarningService,WeatherConstant.STORM_WARNING);

        String stormWarning1 = WeatherUtil.getWeather(WeatherConstant.STORM_WARNING, "1");
        handleWarning(stormWarning1, "Storm1MD5", "Storm1","1",
                WeaStormWarning::new, weaStormWarningService,WeatherConstant.STORM_WARNING);

    }

    /**
     * 极端天气预警
     * 陆基预警
     * @param platform
     */
    private void processWeatherWarning(WeaPlatform platform) {

        String weather = WeatherUtil.getWeather(WeatherConstant.EXTREME_WEATHER_WARNING, platform.getLon() + "," + platform.getLat());
        if (!"[]".equals(weather)) {
            JSONArray jsonArray = new JSONArray(Collections.singletonList(weather));
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonData = jsonArray.getJSONObject(i);
                handleWarning(JSON.toJSONString(jsonData), "WeatherMD5" + platform.getId(), "Weather" + platform.getId(),platform.getId(),
                        WeaWeatherWarning::new, weaWeatherWarningService,WeatherConstant.EXTREME_WEATHER_WARNING);
            }
        }
    }

    /**
     * 海浪预警
     *
     */

    private void processWaveWarning() {

        String wave0 = WeatherUtil.getWeather(WeatherConstant.WAVE_WARNING, "0");
        handleWarning(wave0, "Wave0MD5", "Wave0","1",
                WeaWaveWarning::new, weaWaveWarningService,WeatherConstant.WAVE_WARNING);

        String wave1 = WeatherUtil.getWeather(WeatherConstant.WAVE_WARNING, "1");
        handleWarning(wave1, "Wave1MD5", "Wave1","1",
                WeaWaveWarning::new, weaWaveWarningService,WeatherConstant.WAVE_WARNING);
    }


    /**
     * 判定是否重复方法
     * @param warningData
     * @param redisMd5Key
     * @param redisDataKey
     * @param Id
     * @param warningConstructor
     * @param service
     * @param type
     * @param <T>
     */
    private <T> int handleWarning(String warningData, String redisMd5Key, String redisDataKey, String Id,
                                   Function<JSONObject, T> warningConstructor, Object service, WeatherConstant type) {
        JSONObject jsonData = JSONObject.parseObject(warningData);
        if(redisMd5Key.contains("Typhoon")){
            jsonData.put("parentId", Id);
        }else {
            jsonData.put("platformId",Id );
            if(!Id.equals("1")){
                try {
                    WeaPlatform weaPlatform=weaPlatformService.getById(Id);
                    jsonData.put("platformIdText",weaPlatform.getName());
                } catch (Exception e) {
                    jsonData.put("platformIdText","");
                }
            }

        }


        // 接口提供方可能会随机插入这些值
        jsonData.putIfAbsent("geom", "");
        jsonData.putIfAbsent("image", "");
        jsonData.putIfAbsent("imageType", "");

        String warningUpdate = jsonData.toJSONString();
        String storedMd5 = (String) redisUtil.get(redisMd5Key);
        try {
            String currentMd5 = MD5Util.MD5Encode(warningUpdate, "utf-8");
            jsonData.put("createTime",new Date());
            jsonData.put("id", IdUtil.fastUUID());
            if (storedMd5 == null || !currentMd5.equals(storedMd5)) {
                redisUtil.set(redisMd5Key, currentMd5);
                redisUtil.set(redisDataKey, jsonData.toJSONString());

                T warning = warningConstructor.apply(jsonData);
                saveWarning(service, warning, type);
                return 1;
            } else {
                log.info("数据没有更新:{}", redisDataKey);
            }
        } catch (Exception e) {
            log.error("异常错误: {}", e.getMessage(), e);
        }
        return 0;
    }

    /**
     * 保存方法
     * @param service
     * @param warning
     * @param type
     * @param <T>
     */
    private <T> void saveWarning(Object service, T warning,WeatherConstant type) {
        try {
            switch (type) {
                case STORM_WARNING:
                    ((IWeaStormWarningService) service).saveOrUpdate((WeaStormWarning) warning);
                    break;
                case EXTREME_WEATHER_WARNING:
                    ((IWeaWeatherWarningService) service).saveOrUpdate((WeaWeatherWarning) warning);
                    break;
                case WAVE_WARNING:
                    ((IWeaWaveWarningService) service).saveOrUpdate((WeaWaveWarning) warning);
                    break;
                case SEA_FOG:
                    ((IWeaSeaFogService) service).saveOrUpdate((WeaSeaFog) warning);
                    break;
                case SEA_CONDITIONS:
                    ((IWeaSeaConditionsService) service).saveOrUpdate((WeaSeaConditions) warning);
                    break;
                case SEA_ICE_WARNING:
                    ((IWeaSeaIceService) service).saveOrUpdate((WeaSeaIce) warning);
                    break;
                case TROPICAL_CYCLONE_TRACK:
                    ((IWeaTyphoonTrackDetailService) service).saveOrUpdate((WeaTyphoonTrackDetail) warning);
                    break;
                case TROPICAL_CYCLONE_FORECAST:
                    ((IWeaTyphoonForecastDetailService) service).saveOrUpdate((WeaTyphoonForecastDetail) warning);
                    break;
                case TSUNAMI_WARNING_DETAIL:
                    ((IWeaTsunamiService) service).saveOrUpdate((WeaTsunami) warning);
                    break;
                case SEVEN_DAY_FORECAST:
                    ((IWeaSevenForecastService) service).saveOrUpdate((WeaSevenForecast) warning);
                    break;
                default:
                    log.error("未知类型");
            }

        }catch (Exception e){
            log.error("保存失败错误：", e.getMessage(), e);
        }
    }
}
